package com.yohann.designPattern.singleton;

/**
 * <p>
 * 单例模式
 * 推荐使用饿汉式、双重检查、静态内部类、枚举
 * </p>
 *
 * @author Yohann
 * @since 2021/1/31 20:43
 */
public class SingletonPattern {
}

/**
 * 饿汉式单例
 * <p>
 * 优点：在类装载时就完成了实例化，避免了线程同步问题。
 * 缺点：在类加载时就完成了实例，没有懒加载效果，可能造成内存浪费。
 */
class HungrySingleton {
    /**
     * 自身实例为成员变量
     */
    private static final HungrySingleton INSTANCE = new HungrySingleton();

    /**
     * 私有构造
     */
    private HungrySingleton() {
    }

    /**
     * 对外暴露获取实例对象的方法
     *
     * @return 对象实例
     */
    public static HungrySingleton getInstance() {
        return INSTANCE;
    }
}

/**
 * 饿汉式单例(静态代码块)
 * <p>
 * 在静态代码块中实例化，优缺点与饿汉式一致。
 */
class HungrySingleton2 {
    /**
     * 自身实例为成员变量
     */
    private static HungrySingleton2 instance;

    static {
        instance = new HungrySingleton2();
    }

    /**
     * 私有构造
     */
    private HungrySingleton2() {
    }

    /**
     * 对外暴露获取实例对象的方法
     *
     * @return 对象实例
     */
    public static HungrySingleton2 getInstance() {
        return instance;
    }
}

/**
 * 懒汉式单例
 * <p>
 * 优点：有懒加载作用。
 * 缺点：线程不安全，实际开发不推荐使用。
 */
class LazySingleton {
    /**
     * 自身实例为成员变量
     */
    private static LazySingleton instance;

    /**
     * 私有构造
     */
    private LazySingleton() {
    }

    /**
     * 对外暴露获取实例对象的方法
     *
     * @return 对象实例
     */
    public static LazySingleton getInstance() {
        //获取时实例为空才创建
        if (instance == null) {
            instance = new LazySingleton();
        }

        return instance;
    }
}

/**
 * 懒汉式单例(线程同步)
 * <p>
 * 缺点：效率太低。
 */
class LazySingleton2 {
    /**
     * 自身实例为成员变量
     */
    private static LazySingleton2 instance;

    /**
     * 私有构造
     */
    private LazySingleton2() {
    }

    /**
     * 对外暴露获取实例对象的方法
     *
     * @return 对象实例
     */
    public synchronized static LazySingleton2 getInstance() {
        //获取时实例为空才创建
        if (instance == null) {
            instance = new LazySingleton2();
        }

        return instance;
    }
}

/**
 * 懒汉式单例(同步代码块)
 * <p>
 * 缺点：效率太低。
 */
class LazySingleton3 {
    /**
     * 自身实例为成员变量
     */
    private static LazySingleton3 instance;

    /**
     * 私有构造
     */
    private LazySingleton3() {
    }

    /**
     * 对外暴露获取实例对象的方法
     *
     * @return 对象实例
     */
    public static LazySingleton3 getInstance() {
        //获取时实例为空才创建
        if (instance == null) {
            synchronized (LazySingleton3.class) {
                instance = new LazySingleton3();
            }
        }

        return instance;
    }
}

/**
 * 双重检查
 * <p>
 * 优点：有懒加载，解决线程安全问题，兼顾效率，推荐使用。
 */
class DoubleCheckSingleton {
    /**
     * 自身实例为成员变量
     */
    private static DoubleCheckSingleton instance;

    /**
     * 私有构造
     */
    private DoubleCheckSingleton() {
    }

    /**
     * 对外暴露获取实例对象的方法
     *
     * @return 对象实例
     */
    public static DoubleCheckSingleton getInstance() {
        //获取时实例为空才创建
        if (instance == null) {

            synchronized (DoubleCheckSingleton.class) {
                //双重检查 保证创建一个实例
                if (instance == null) {
                    instance = new DoubleCheckSingleton();
                }
            }
        }

        return instance;
    }
}

/**
 * 静态内部类
 * <p>
 * 优点：有懒加载，解决线程安全问题（类加载时线程安全）。
 */
class StaticInnerClassSingleton {
    /**
     * 私有构造
     */
    private StaticInnerClassSingleton() {
    }

    /**
     * 在静态内部类中实例化
     */
    private static class SingleInstance {
        private static final StaticInnerClassSingleton INSTANCE = new StaticInnerClassSingleton();
    }

    /**
     * 对外暴露获取实例对象的方法
     *
     * @return 对象实例
     */
    public static StaticInnerClassSingleton getInstance() {
        return SingleInstance.INSTANCE;
    }
}

/**
 * 枚举
 * <p>
 * 优点：防止反序列化创建新对象，推荐使用。
 */
enum EnumSingleton {
    /**
     * 实例
     */
    INSTANCE;
}